/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package eu.easyedu.dictionary.explorer;

import eu.easyedu.dictionary.api.resources.Bundle;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.text.JTextComponent;

/**
 *
 * @author hlavki
 */
public class Validator extends JComponent {

    private static final long serialVersionUID = 1L;
    private static final Logger log = Logger.getLogger(Validator.class.getName());
    private Set<JComponent> invalidFields = new HashSet<JComponent>();
    private Set<JTextComponent> fields = new HashSet<JTextComponent>();
    private BufferedImage warningIcon;
    private Component parent;

    /** Creates a new instance of Validator */
    public Validator(Component parent) {
        loadImages();
        this.parent = parent;
    }

    protected void removeWarning(JComponent field) {
        if (invalidFields.contains(field)) {
            log.info("Removing warning to component " + field.getName());
            invalidFields.remove(field);
            if (parent.isVisible()) {
                repaintBadge(field);
            }
        }
    }

    protected void addWarning(JComponent field) {
        log.info("Adding warning to component " + field.getName());
        invalidFields.add(field);
        if (parent.isVisible()) {
            repaintBadge(field);
        }
    }

    public final void addValidation(JTextComponent field, final String regexPattern) {
        field.addFocusListener(new FocusListener() {

            public void focusGained(FocusEvent focusEvent) {
            }

            public void focusLost(FocusEvent focusEvent) {
                JTextComponent field = (JTextComponent) focusEvent.getComponent();
                String text = field.getText();
                // default value "[-A-Za-z0-9 ]+"
                if (text.matches(regexPattern)) {
                    removeWarning(field);
                } else {
                    addWarning(field);
                }
            }
        });
        fields.add(field);
    }

    private final void repaintBadge(JComponent field) {
        Point p = field.getLocationOnScreen();
        SwingUtilities.convertPointFromScreen(p, this);

        int x = p.x - warningIcon.getWidth() / 2;
        int y = (int) (p.y + field.getHeight() - warningIcon.getHeight() / 1.5);

        repaint(x, y, warningIcon.getWidth(), warningIcon.getHeight());
    }

    private final void loadImages() {
        try {
            warningIcon = ImageIO.read(Bundle.getClasspathResource("warning2.png"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        for (JComponent invalid : invalidFields) {
            if (invalid.getParent() instanceof JViewport) {
                JViewport viewport = (JViewport) invalid.getParent();
                // the parent of the viewport is a JScrollPane
                invalid = (JComponent) viewport.getParent();
            }

            Point p = invalid.getLocationOnScreen();
            SwingUtilities.convertPointFromScreen(p, this);

            int x = p.x - warningIcon.getWidth() / 2;
            int y = (int) (p.y + invalid.getHeight() - warningIcon.getHeight() / 1.5);

            if (g.getClipBounds().intersects(x, y,
                    warningIcon.getWidth(), warningIcon.getHeight())) {
                g.drawImage(warningIcon, x, y, null);
            }
        }
    }

    public boolean isCorrect() {
        return invalidFields.size() == 0;
    }

    public int invalidFieldsCount() {
        return invalidFields.size();
    }
    
    public final void refreshValidation(Component actualFocus) {
        for (JComponent component : fields) {
            component.requestFocus();
        }
        actualFocus.requestFocus();
    }
}
